Skip to content

fix(release): give gh the repo, and make a tagged release recoverable - #71

Merged
MotherSphere merged 1 commit into
mainfrom
fix/release-recovery
Aug 27, 2026
Merged

fix(release): give gh the repo, and make a tagged release recoverable#71
MotherSphere merged 1 commit into
mainfrom
fix/release-recovery

Conversation

@MotherSphere

Copy link
Copy Markdown
Member

v0.10.0 shipped as a tagged, published, EMPTY release. This is why, and what
stops it recurring.

The draft-hold step added in #70 runs in the release-please job, which has no
actions/checkout. gh infers the repository from the git remote, found none,
and died with "fatal: not a git repository". The job failed, so build, sign and
aur all skipped - and because release-please had already published the release,
/releases/latest moved to a v0.10.0 with zero assets. Every running Colony was
offered an update that does not exist, until the release was re-drafted by hand
and latest fell back to v0.9.2.

aur-publish.yml already carries the warning for exactly this ("-R is not
optional here. This job has no actions/checkout"), and the new call was added
without heeding it. Every gh call in the workflow now passes -R explicitly,
so where a job sits can no longer decide whether it works.

The second half is that the pipeline had no way to finish a release once
release-please had emitted its one release_created. "Re-run all jobs" makes
release-please report nothing to do and every downstream job skip while the run
reports green, which looks like a successful recovery and is the opposite of
one. So a failure anywhere left a tagged release permanently unfinishable except
by signing four binaries by hand.

workflow_dispatch with a tag input fixes that. A new target job resolves
which tag the run is for - from release-please on a merge, from the input on a
dispatch - and build, sign and aur read it instead of reaching into
release-please's outputs. Both checkouts pin ref: to that tag, because the
default ref on a dispatch is the branch, and rebuilding from a different commit
than the tag names would produce binaries the .meta sidecar then binds to a
version they were not built from.

v0.10.0 shipped as a tagged, published, EMPTY release. This is why, and what
stops it recurring.

The draft-hold step added in #70 runs in the `release-please` job, which has no
`actions/checkout`. `gh` infers the repository from the git remote, found none,
and died with "fatal: not a git repository". The job failed, so build, sign and
aur all skipped - and because release-please had already published the release,
/releases/latest moved to a v0.10.0 with zero assets. Every running Colony was
offered an update that does not exist, until the release was re-drafted by hand
and latest fell back to v0.9.2.

aur-publish.yml already carries the warning for exactly this ("`-R` is not
optional here. This job has no `actions/checkout`"), and the new call was added
without heeding it. Every `gh` call in the workflow now passes `-R` explicitly,
so where a job sits can no longer decide whether it works.

The second half is that the pipeline had no way to finish a release once
release-please had emitted its one `release_created`. "Re-run all jobs" makes
release-please report nothing to do and every downstream job skip while the run
reports green, which looks like a successful recovery and is the opposite of
one. So a failure anywhere left a tagged release permanently unfinishable except
by signing four binaries by hand.

`workflow_dispatch` with a tag input fixes that. A new `target` job resolves
which tag the run is for - from release-please on a merge, from the input on a
dispatch - and build, sign and aur read it instead of reaching into
release-please's outputs. Both checkouts pin `ref:` to that tag, because the
default ref on a dispatch is the branch, and rebuilding from a different commit
than the tag names would produce binaries the .meta sidecar then binds to a
version they were not built from.

Three things an adversarial review of this change caught before it merged:

- The `target` job read `needs.target.outputs.tag` - itself. The mechanical
  rewrite that repointed every consumer at the new job also rewrote the one line
  that was supposed to be the SOURCE. On a dispatch it is harmless because the
  input fills in, so the planned v0.10.0 recovery run would have gone green
  while every future merge failed to resolve a tag and left exactly the empty
  tagged draft this commit exists to prevent.
- `if: always()` on `target` would also have run it when release-please FAILED,
  removing the brake that stopped the v0.10.0 incident at an empty draft rather
  than a broken build. `!cancelled() && !failure()` still runs when
  release-please is SKIPPED, which is what a dispatch does.
- The uploader has overwrite_files on by default, so dispatching against an
  already-published tag would delete and replace its live binaries and only then
  hit the draft assertion - leaving published assets whose .sig and .meta
  describe bytes that no longer exist. Since verification is fail-closed, that
  breaks every install of that version. `target` now refuses any tag whose
  release is not a draft, before anything is uploaded.
@MotherSphere
MotherSphere merged commit 836f2e2 into main Aug 27, 2026
5 checks passed
@MotherSphere
MotherSphere deleted the fix/release-recovery branch August 27, 2026 21:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant